package space.enemy;

import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.shape.Shape;
//import org.anddev.andengine.util.Debug;

/**
 * @author Nicolas Gramlich
 * @since 15:36:26 - 19.07.2010
 * @updated Aaron Stone
 * @since 12.10.2010
 */
public class ParallaxBackground extends ColorBackground {
	// ===========================================================
	// Constants
	// ===========================================================

	// ===========================================================
	// Fields
	// ===========================================================

	private final ArrayList<ParallaxEntity> mParallaxEntities = new ArrayList<ParallaxEntity>();
	private int mParallaxEntityCount;

	protected float mParallaxValue;

	// ===========================================================
	// Constructors
	// ===========================================================

	public ParallaxBackground(final float pRed, final float pGreen, final float pBlue) {
		super(pRed, pGreen, pBlue);
	}

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	public void setParallaxValue(final float pParallaxValue) {
		this.mParallaxValue = pParallaxValue;
	}

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	public void onDraw(final GL10 pGL, final Camera pCamera) {
		super.onDraw(pGL, pCamera);

		final float parallaxValue = this.mParallaxValue;
		final ArrayList<ParallaxEntity> parallaxEntities = this.mParallaxEntities;

		for(int i = 0; i < this.mParallaxEntityCount; i++) {
			parallaxEntities.get(i).onDraw(pGL, parallaxValue, pCamera);
		}
	}

	// ===========================================================
	// Methods
	// ===========================================================

	public int addParallaxEntity(final ParallaxEntity pParallaxEntity) {
		this.mParallaxEntities.add(pParallaxEntity);
		this.mParallaxEntityCount++;
		return (mParallaxEntityCount - 1); 
	}

	public void updateParallaxEntity(int entitynumber, float pParallaxXFactor, float pParallaxYFactor)
	{
		this.mParallaxEntities.get(entitynumber).ParallaxUpdate(pParallaxXFactor, pParallaxYFactor);
	}
	
	public boolean removeParallaxEntity(final ParallaxEntity pParallaxEntity) {
		this.mParallaxEntityCount--;
		final boolean success = this.mParallaxEntities.remove(pParallaxEntity);
		if(success == false) {
			this.mParallaxEntityCount++;
		}
		return success;
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

	public static class ParallaxEntity {
		// ===========================================================
		// Constants
		// ===========================================================

		// ===========================================================
		// Fields
		// ===========================================================

		float lastX;
		float lastY;
		float mParallaxXFactor;
		float mParallaxYFactor;
		Boolean mParallaxXRepeat;
		Boolean mParallaxYRepeat;
		final Shape mShape;

		// ===========================================================
		// Constructors
		// ===========================================================

		public ParallaxEntity(float pParallaxXFactor, float pParallaxYFactor, 
				              Boolean pParallaxXRepeat, Boolean pParallaxYRepeat, final Shape pShape) 
		{
			this.mParallaxXFactor = pParallaxXFactor;
			this.mParallaxYFactor = pParallaxYFactor;
			this.mParallaxXRepeat = pParallaxXRepeat;
			this.mParallaxYRepeat = pParallaxYRepeat;
			this.mShape = pShape;
			lastX = 0;
			lastY = 0;
		}

		// ===========================================================
		// Getter & Setter
		// ===========================================================
		public void ParallaxUpdate(float pParallaxXFactor, float pParallaxYFactor)
		{
			this.mParallaxXFactor = pParallaxXFactor;
			this.mParallaxYFactor = pParallaxYFactor;			
		}
		
		// ===========================================================
		// Methods for/from SuperClass/Interfaces
		// ===========================================================

		// ===========================================================
		// Methods
		// ===========================================================

		public void onDraw(final GL10 pGL, final float pParallaxValue, final Camera pCamera) {
			pGL.glPushMatrix();
			{
				final float cameraWidth = pCamera.getWidth();
				final float cameraHeight = pCamera.getHeight();
				final float shapeWidthScaled = this.mShape.getWidthScaled();
				final float shapeHeightScaled = this.mShape.getHeightScaled();
				//float baseXOffset = (pParallaxValue * this.mParallaxXFactor) % shapeWidthScaled;
				//float baseYOffset = (pParallaxValue * this.mParallaxYFactor) % shapeHeightScaled;
				float baseXOffset = lastX + (pParallaxValue * this.mParallaxXFactor);
				float baseYOffset = lastY + (pParallaxValue * this.mParallaxYFactor);
				
				while (baseXOffset < -shapeWidthScaled)
					baseXOffset += shapeWidthScaled;
				while (baseYOffset < -shapeHeightScaled)
					baseYOffset += shapeHeightScaled;
				while(baseXOffset > 0)
					baseXOffset -= shapeWidthScaled;
				while(baseYOffset > 0)
					baseYOffset -= shapeHeightScaled;
				//Debug.i("AMS: baseX " + baseXOffset + " baseY " + baseYOffset);
				
				lastX = baseXOffset;
				lastY = baseYOffset;
				
				pGL.glTranslatef(baseXOffset, baseYOffset, 0);

				float currentMaxX = baseXOffset;
				float currentMaxY = baseYOffset;

				if (mParallaxXRepeat && mParallaxYRepeat)
				{
					do 
					{
						do 
						{
							this.mShape.onDraw(pGL, pCamera);
							pGL.glTranslatef(0, shapeHeightScaled, 0);
							currentMaxY += shapeHeightScaled;
						} while(currentMaxY < cameraHeight);
						pGL.glTranslatef(0, -(currentMaxY-baseYOffset), 0);
						currentMaxY = baseYOffset;
					
						pGL.glTranslatef(shapeWidthScaled, 0, 0);
						currentMaxX += shapeWidthScaled;
					} while(currentMaxX < cameraWidth);
				}
				else if (mParallaxXRepeat) 
				{
					do {
						this.mShape.onDraw(pGL, pCamera);
						pGL.glTranslatef(shapeWidthScaled, 0, 0);
						currentMaxX += shapeWidthScaled;
					} while(currentMaxX < cameraWidth);					
				}
				else if (mParallaxYRepeat)
				{
					do {
						this.mShape.onDraw(pGL, pCamera);
						pGL.glTranslatef(0, shapeHeightScaled, 0);
						currentMaxY += shapeHeightScaled;					
					} while(currentMaxY < cameraHeight);				
				} 
			}
			pGL.glPopMatrix();
		}

		// ===========================================================
		// Inner and Anonymous Classes
		// ===========================================================
	}
}
